package com.test.exoplayertest.player.view;

import android.annotation.TargetApi;
import android.content.Context;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;

import com.google.android.exoplayer2.C;
import com.google.android.exoplayer2.ExoPlaybackException;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.PlaybackParameters;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.Timeline;
import com.google.android.exoplayer2.source.TrackGroupArray;
import com.google.android.exoplayer2.trackselection.TrackSelectionArray;
import com.test.exoplayertest.R;
import com.test.exoplayertest.player.utils.PlayerUtil;

/**
 * 播放器控制面板
 *
 * @author wuxiaotao on 2017/6/16.
 */

public class PlayerPanelView extends RelativeLayout {

    private TextView position_text;
    private TextView duration_text;
    private SeekBar seekbar;
    private ImageView play_btn;

    private ImageView orientation_btn;

    private SimpleExoPlayer mExoPlayer;
    private boolean isAttachedToWindow;
    private long showTimeoutMs = 5000;
    private long hideAtMs;
    private boolean isSeekbarInTouch = false;
    private ComponentListener componentListener;
    public static final String TAG = "PlayerPanelView";


    //更新时间进度
    private final Runnable updateProgressAction = new Runnable() {
        @Override
        public void run() {
            updateProgress();
        }
    };

    //显示隐藏控制
    private final Runnable hideAction = new Runnable() {
        @Override
        public void run() {
            hide();
        }
    };

    public PlayerPanelView(Context context) {
        this(context, null);
    }

    public PlayerPanelView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PlayerPanelView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    @TargetApi(21)
    public PlayerPanelView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init(context);
    }

    private void init(Context context) {
        LayoutInflater.from(context).inflate(R.layout.player_float_panel_view, this);
        position_text = (TextView) findViewById(R.id.position_text);
        duration_text = (TextView) findViewById(R.id.duration_text);
        seekbar = (SeekBar) findViewById(R.id.seekbar);
        play_btn = (ImageView) findViewById(R.id.play_btn);
        componentListener = new ComponentListener();
        play_btn.setOnClickListener(componentListener);
        seekbar.setOnSeekBarChangeListener(componentListener);
        orientation_btn = (ImageView) findViewById(R.id.orientation_btn);
    }

    public void setExoPlayer(SimpleExoPlayer exoPlayer) {
        release();
        this.mExoPlayer = exoPlayer;
        if (mExoPlayer != null) {
            Log.e(TAG, "playerPanelView  addListenner");
            mExoPlayer.addListener(componentListener);
        }
        updateProgress();
    }

    public void setChildClickListenner(OnClickListener listenner){
        orientation_btn.setOnClickListener(listenner);
    }

    public void release(){
        if (this.mExoPlayer != null) {
            Log.e(TAG, "playerPanelView  release");
            this.mExoPlayer.removeListener(componentListener);
        }
    }

    public boolean isVisible() {
        return getVisibility() == VISIBLE;
    }

    public void show() {
        if (!isVisible()) {
            setVisibility(VISIBLE);
            updateAll();
//            requestPlayPauseFocus();
        }
        // Call hideAfterTimeout even if already visible to reset the timeout.
        hideAfterTimeout();
    }

    public void hide() {
        if (isVisible()) {
            setVisibility(GONE);
            removeCallbacks(updateProgressAction);
            removeCallbacks(hideAction);
            hideAtMs = C.TIME_UNSET;
        }
    }

    private void hideAfterTimeout() {
        removeCallbacks(hideAction);
        if (showTimeoutMs > 0) {
            hideAtMs = SystemClock.uptimeMillis() + showTimeoutMs;
            if (isAttachedToWindow) {
                postDelayed(hideAction, showTimeoutMs);
            }
        } else {
            hideAtMs = C.TIME_UNSET;
        }
    }

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        isAttachedToWindow = true;
        if (hideAtMs != C.TIME_UNSET) {
            long delayMs = hideAtMs - SystemClock.uptimeMillis();
            if (delayMs <= 0) {
                hide();
            } else {
                postDelayed(hideAction, delayMs);
            }
        }
        updateAll();
    }

    @Override
    public void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        isAttachedToWindow = false;
        removeCallbacks(updateProgressAction);
        removeCallbacks(hideAction);
    }

    private void updateAll() {
        updateProgress();
    }

    private void updateProgress() {
        if (!isVisible() || !isAttachedToWindow) {
            return;
        }

        long position = 0;
        long bufferedPosition = 0;
        long duration = 0;
        if (mExoPlayer != null) {
            position = mExoPlayer.getCurrentPosition();
            bufferedPosition = mExoPlayer.getBufferedPosition();
            duration = mExoPlayer.getDuration();
        }
        Log.e(TAG, "===当前位置===" + position);
        Log.e(TAG, "===缓存位置===" + bufferedPosition);
        Log.e(TAG, "===总的时长===" + duration);
        duration_text.setText(PlayerUtil.getDuration(duration));
        int max = (int) (duration / 1000);
        int current = (int) (position / 1000);
        int second = (int) (bufferedPosition / 1000);
        if (seekbar.getMax() != max) {
            seekbar.setMax(max);
        }
        //seekbar 手动滑动时 不处理
        if(!isSeekbarInTouch){
            position_text.setText(PlayerUtil.getDuration(position));
            seekbar.setProgress(current);
        }
        seekbar.setSecondaryProgress(second);
        // Cancel any pending updates and schedule a new one if necessary.
        removeCallbacks(updateProgressAction);
        int playbackState = mExoPlayer == null ? ExoPlayer.STATE_IDLE : mExoPlayer.getPlaybackState();
        if (playbackState != ExoPlayer.STATE_IDLE && playbackState != ExoPlayer.STATE_ENDED) {
            long delayMs;
            if (mExoPlayer.getPlayWhenReady() && playbackState == ExoPlayer.STATE_READY) {
                delayMs = 1000 - (position % 1000);
                if (delayMs < 200) {
                    delayMs += 1000;
                }
            } else {
                delayMs = 1000;
            }
            postDelayed(updateProgressAction, delayMs);
        }
    }

    private void updatePlayPauseButton() {
        if (!isVisible() || !isAttachedToWindow) {
            return;
        }
        boolean playing = mExoPlayer != null && mExoPlayer.getPlayWhenReady();
        play_btn.setImageResource(playing ? R.mipmap.btn_pause_normal : R.mipmap.btn_play_normal);
    }

    public void onConfigurationChanged(boolean isLand){
        if(isLand){
            orientation_btn.setImageResource(R.mipmap.player_orientation_switch_btn_portrait_normal);
        }else{
            orientation_btn.setImageResource(R.mipmap.player_orientation_switch_btn_landscape_normal);
        }
    }

    private final class ComponentListener implements ExoPlayer.EventListener, OnClickListener, SeekBar.OnSeekBarChangeListener {

        private boolean touchPlayerReady = true;//记录seekbar拖动前，player是否正在播放

        @Override
        public void onTimelineChanged(Timeline timeline, Object manifest) {
            Log.e(TAG, "======onTimelineChanged=====");
            updateProgress();
        }

        @Override
        public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {

        }

        @Override
        public void onLoadingChanged(boolean isLoading) {

        }

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            Log.e(TAG, "======onPlayerStateChanged=====");
            updatePlayPauseButton();
            updateProgress();
        }

        @Override
        public void onPlayerError(ExoPlaybackException error) {

        }

        @Override
        public void onPositionDiscontinuity() {

        }

        @Override
        public void onPlaybackParametersChanged(PlaybackParameters playbackParameters) {

        }

        @Override
        public void onClick(View v) {
            if(v == play_btn){
                mExoPlayer.setPlayWhenReady(!mExoPlayer.getPlayWhenReady());
                show();
            }
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            Log.e(TAG,"====onProgressChanged===="+ progress+"  === fromUser "+ fromUser);
            if(position_text != null && fromUser){
                position_text.setText(PlayerUtil.getDuration(progress * 1000));
            }
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            Log.e(TAG,"====onStartTrackingTouch===="+ seekBar.getProgress());
            isSeekbarInTouch = true;
            touchPlayerReady = mExoPlayer.getPlayWhenReady();
            mExoPlayer.setPlayWhenReady(false);
            removeCallbacks(hideAction);
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            Log.e(TAG,"====onStopTrackingTouch===="+ seekBar.getProgress());
            isSeekbarInTouch = false;
            int progress = seekBar.getProgress();
            mExoPlayer.seekTo(progress * 1000);
            mExoPlayer.setPlayWhenReady(touchPlayerReady);
            hideAfterTimeout();
        }
    }
}
